package com.link2room.rodimus.service.impl;

import com.link2room.common.constant.DefaultValue;
import com.link2room.common.dao.ICommonDao;
import com.link2room.common.entity.BaseEntity;
import com.link2room.common.enums.BaseSysExceptionEnum;
import com.link2room.common.exception.SysException;
import com.link2room.common.jpa.condition.ConditionDetail;
import com.link2room.common.jpa.condition.L2RCondition;
import com.link2room.common.jpa.criteria.CriteriaUtil;
import com.link2room.common.jpa.result.QueryResult;
import com.link2room.common.service.ICommonService;
import com.link2room.common.util.*;
import com.link2room.rodimus.constant.SignInConstant;
import com.link2room.rodimus.dto.param.base.SignInAwardBaseDto;
import com.link2room.rodimus.dto.param.base.SignInBaseDto;
import com.link2room.rodimus.dto.param.base.SignInReissueRuleResvDto;
import com.link2room.rodimus.dto.param.base.SignInReissueRuleShareDto;
import com.link2room.rodimus.entity.*;
import com.link2room.rodimus.mapper.SignInAwardMapper;
import com.link2room.rodimus.mapper.SignInReissueMapper;
import com.link2room.rodimus.service.ISignInService;
import com.link2room.rodimus.util.CalendarUtils;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

import static com.link2room.enums.exception.RodimusSysExceptionEnum.GET_UNDERWAY_SIGN_BASE_ERROR;
import static com.link2room.enums.exception.RodimusSysExceptionEnum.SIGN_IN_REISSUE;

/**
 * Created by LN on 2018/1/5
 */
@Component("signInService")
public class SignInServiceImpl implements ISignInService {

    @Resource
    private ICommonDao commonDao;
    @Resource
    private ICommonService commonService;
    @Autowired
    private RedisLockRegistry signInCodeLock;

    @Override
    @Transactional
    public SignInDetailEntity reissue(String lhotelGroupCode, Date reissueDate, String memberNo) throws Exception {
        Date signDate = CalendarUtils.getDateWithOutTime(reissueDate);
        Date month = CalendarUtils.getStartTimeOfMonth(signDate);
        SignInReissueBaseEntity find = new SignInReissueBaseEntity();
        find.setLhotelGroupCode(lhotelGroupCode);
        find.setMemberNo(memberNo);
        find.setMonth(month);
        SignInReissueBaseEntity qres = commonService.findOnlyOneEQ(SignInReissueBaseEntity.class, find);
        L2RAssert.isTrue(null == qres, new SysException(SIGN_IN_REISSUE, "当月没有补签机会"));
        L2RAssert.isTrue(qres.getUsed() >= qres.getTotal(), new SysException(SIGN_IN_REISSUE, "当月没有补签机会"));

        SignInDetailEntity newSign = new SignInDetailEntity();
        newSign.setSignInDate(signDate);
        newSign.setLhotelGroupCode(lhotelGroupCode);
        newSign.setMemberNo(memberNo);
        newSign.setIsReissue(DefaultValue.T);

        qres.setUsed(qres.getUsed() + 1);

        commonDao.save(newSign);
        commonDao.merge(qres);
        return newSign;
    }

    @Override
    public SignInBaseDto getUnderwaySignBaseWithAwardInfo(String lhotelGroupCode) throws Exception {
        Date now = new Date();
        L2RCondition signInBaseCondition = new L2RCondition();
        signInBaseCondition.setAndConditions(
                new ConditionDetail[]{
                        new ConditionDetail(SignInRuleBaseEntity.SignInRuleBaseEntity_.isAutoExtension.toString(), CriteriaUtil.Operator.EQ, DefaultValue.F),
                        new ConditionDetail(SignInRuleBaseEntity.SignInRuleBaseEntity_.startMonth.toString(), CriteriaUtil.Operator.LT, now),
                        new ConditionDetail(SignInRuleBaseEntity.SignInRuleBaseEntity_.endMonth.toString(), CriteriaUtil.Operator.GT, DateUtil.addMonths(now,-1)),
                        new ConditionDetail(SignInRuleBaseEntity.BaseEntity_.lhotelGroupCode.toString(), CriteriaUtil.Operator.EQ, lhotelGroupCode),
                }
        );
        QueryResult<SignInRuleBaseEntity> signInBaseQres = commonService.findAllByCondition(SignInRuleBaseEntity.class, signInBaseCondition);
        if (CollectionUtils.isEmpty(signInBaseQres.getResultlist())) {
            signInBaseCondition = new L2RCondition();
            signInBaseCondition.setAndConditions(
                    new ConditionDetail[]{
                            new ConditionDetail(SignInRuleBaseEntity.SignInRuleBaseEntity_.isAutoExtension.toString(), CriteriaUtil.Operator.EQ, DefaultValue.T),
                            new ConditionDetail(SignInRuleBaseEntity.SignInRuleBaseEntity_.startMonth.toString(), CriteriaUtil.Operator.LT, now),
                            new ConditionDetail(SignInRuleBaseEntity.BaseEntity_.lhotelGroupCode.toString(), CriteriaUtil.Operator.EQ, lhotelGroupCode),
                    }
            );
            signInBaseQres = commonService.findAllByCondition(SignInRuleBaseEntity.class, signInBaseCondition);
        }
        if (CollectionUtils.isEmpty(signInBaseQres.getResultlist())) {
            return null;
        } else {
            L2RAssert.isTrue(signInBaseQres.getResultlist().size() > 1, new SysException(GET_UNDERWAY_SIGN_BASE_ERROR, "数据异常,当前有效活动大于1个," + signInBaseQres.getResultlist().stream().map(SignInRuleBaseEntity::getCode).collect(Collectors.toList())));
        }
        SignInRuleBaseEntity signInRuleBaseEntity = signInBaseQres.getResultlist().get(0);

        String ruleCode = signInRuleBaseEntity.getCode();
        QueryResult<SignInAwardMapper> qres = findSignInAwardMapper(lhotelGroupCode, ruleCode, now);
        List<SignInAwardBaseDto> signInAwardBaseDtos = qres.getResultlist().stream()
                .map(awardMapper -> {
                    SignInAwardBaseDto abd = new SignInAwardBaseDto();
                    abd.setCouldLoopDraw(awardMapper.getIsContinuous());
                    abd.setCode(awardMapper.getAwardCode());
                    abd.setType(awardMapper.getType());
                    abd.setTypeName(awardMapper.getTypeName());
                    abd.setDescription(awardMapper.getDescription());
                    abd.setLhotelGroupCode(lhotelGroupCode);
                    abd.setDayNum(awardMapper.getDayStep());
                    abd.setValue(awardMapper.getValue());
                    return abd;
                })
                .collect(Collectors.toList());
        SignInBaseDto signInBaseDto = ClassConverUtil.copyPropertiesToDto(signInRuleBaseEntity, SignInBaseDto.class, true);
        signInBaseDto.setSignInAwardBases(signInAwardBaseDtos);
        return signInBaseDto;
    }

    @Override
    public boolean hasUnderwaySignBase(String lhotelGroupCode) throws Exception {
        Date now = new Date();
        L2RCondition signInBaseCondition = new L2RCondition();
        signInBaseCondition.setAndConditions(
                new ConditionDetail[]{
                        new ConditionDetail(SignInRuleBaseEntity.SignInRuleBaseEntity_.isAutoExtension.toString(), CriteriaUtil.Operator.EQ, DefaultValue.F),
                        new ConditionDetail(SignInRuleBaseEntity.SignInRuleBaseEntity_.startMonth.toString(), CriteriaUtil.Operator.LT, now),
                        new ConditionDetail(SignInRuleBaseEntity.SignInRuleBaseEntity_.endMonth.toString(), CriteriaUtil.Operator.GT, DateUtil.addMonths(now,-1)),
                        new ConditionDetail(SignInRuleBaseEntity.BaseEntity_.lhotelGroupCode.toString(), CriteriaUtil.Operator.EQ, lhotelGroupCode),
                }
        );
        QueryResult<SignInRuleBaseEntity> signInBaseQres = commonService.findAllByCondition(SignInRuleBaseEntity.class, signInBaseCondition);
        if (CollectionUtils.isEmpty(signInBaseQres.getResultlist())) {
            signInBaseCondition = new L2RCondition();
            signInBaseCondition.setAndConditions(
                    new ConditionDetail[]{
                            new ConditionDetail(SignInRuleBaseEntity.SignInRuleBaseEntity_.isAutoExtension.toString(), CriteriaUtil.Operator.EQ, DefaultValue.T),
                            new ConditionDetail(SignInRuleBaseEntity.SignInRuleBaseEntity_.startMonth.toString(), CriteriaUtil.Operator.LT, now),
                            new ConditionDetail(SignInRuleBaseEntity.BaseEntity_.lhotelGroupCode.toString(), CriteriaUtil.Operator.EQ, lhotelGroupCode),
                    }
            );
            signInBaseQres = commonService.findAllByCondition(SignInRuleBaseEntity.class, signInBaseCondition);
        }
        return CollectionUtils.isNotEmpty(signInBaseQres.getResultlist());
    }

    @Override
    public SignInBaseDto getUnderwaySignInBaseAll(String lhotelGroupCode) throws Exception {
        SignInBaseDto res = this.getUnderwaySignBaseWithAwardInfo(lhotelGroupCode);
        if (null == res) {
            return null;
        }
        //是否可以补签
//        if (DefaultValue.F.equals(res.getCouldReissue())) {
//            return res;
//        }
        Date now = new Date();
        QueryResult<SignInReissueMapper> qres = findSignInReissueMapper(lhotelGroupCode, res.getCode(), now);
        if (null == qres || CollectionUtils.isEmpty(qres.getResultlist())) {
            return res;
        } else {
            Map<String, List<SignInReissueMapper>> typeReissueRuleMap = qres.getResultlist()
                    .stream().collect(Collectors.groupingBy(SignInReissueMapper::getType));
            List<SignInReissueMapper> resvRuleList = typeReissueRuleMap.get(SignInConstant.ReissueType.RESV);
            if (CollectionUtils.isNotEmpty(resvRuleList)) {
                SignInReissueMapper resvRule = resvRuleList.get(0);
                if (StringUtil.isNotBlank(resvRule.getRule())) {
                    res.setSignInReissueRuleResv(JacksonUtil.jsonToBean(resvRule.getRule(), SignInReissueRuleResvDto.class));
                }
            }
            List<SignInReissueMapper> shareRuleList = typeReissueRuleMap.get(SignInConstant.ReissueType.SHAER);
            if (CollectionUtils.isNotEmpty(shareRuleList)) {
                SignInReissueMapper shareRule = shareRuleList.get(0);
                if (StringUtil.isNotBlank(shareRule.getRule())) {
                    res.setSignInReissueRuleShare(JacksonUtil.jsonToBean(shareRule.getRule(), SignInReissueRuleShareDto.class));
                }
            }
            return res;
        }
    }

    private SignInBaseDto selectSignRuleDetail(SignInRuleBaseEntity entity) throws Exception {
        String ruleCode = entity.getCode();
        String lhotelGroupCode = entity.getLhotelGroupCode();
        QueryResult<SignInAwardMapper> qres = findSignInAwardMapper(lhotelGroupCode, ruleCode, entity.getStartMonth());
        List<SignInAwardBaseDto> signInAwardBaseDtos = qres.getResultlist().stream()
                .map(awardMapper -> {
                    SignInAwardBaseDto abd = new SignInAwardBaseDto();
                    abd.setCouldLoopDraw(awardMapper.getIsContinuous());
                    abd.setCode(awardMapper.getAwardCode());
                    abd.setType(awardMapper.getType());
                    abd.setTypeName(awardMapper.getTypeName());
                    abd.setDescription(awardMapper.getDescription());
                    abd.setLhotelGroupCode(lhotelGroupCode);
                    abd.setDayNum(awardMapper.getDayStep());
                    abd.setValue(awardMapper.getValue());
                    return abd;
                })
                .collect(Collectors.toList());
        SignInBaseDto signInBaseDto = ClassConverUtil.copyPropertiesToDto(entity, SignInBaseDto.class, true);
        signInBaseDto.setIsInUse(_isInUse(entity) ? DefaultValue.T : DefaultValue.F);
        signInBaseDto.setIsOver(_isOver(entity) ? DefaultValue.T : DefaultValue.F);
        signInBaseDto.setSignInAwardBases(signInAwardBaseDtos);


        QueryResult<SignInReissueMapper> reissueQres = findSignInReissueMapper(lhotelGroupCode, signInBaseDto.getCode(), signInBaseDto.getStartMonth());
        if (null == reissueQres || CollectionUtils.isEmpty(reissueQres.getResultlist())) {
            return signInBaseDto;
        } else {
            Map<String, List<SignInReissueMapper>> typeReissueRuleMap = reissueQres.getResultlist()
                    .stream().collect(Collectors.groupingBy(SignInReissueMapper::getType));
            List<SignInReissueMapper> resvRuleList = typeReissueRuleMap.get(SignInConstant.ReissueType.RESV);
            if (CollectionUtils.isNotEmpty(resvRuleList)) {
                SignInReissueMapper resvRule = resvRuleList.get(0);
                if (StringUtil.isNotBlank(resvRule.getRule())) {
                    signInBaseDto.setSignInReissueRuleResv(JacksonUtil.jsonToBean(resvRule.getRule(), SignInReissueRuleResvDto.class));
                }
            }
            List<SignInReissueMapper> shareRuleList = typeReissueRuleMap.get(SignInConstant.ReissueType.SHAER);
            if (CollectionUtils.isNotEmpty(shareRuleList)) {
                SignInReissueMapper shareRule = shareRuleList.get(0);
                if (StringUtil.isNotBlank(shareRule.getRule())) {
                    signInBaseDto.setSignInReissueRuleShare(JacksonUtil.jsonToBean(shareRule.getRule(), SignInReissueRuleShareDto.class));
                }
            }
            return signInBaseDto;
        }
    }

    @Override
    public QueryResult<SignInBaseDto> getSignInRuleBaseAll(String lhotelGroupCode, Integer currentPage, Integer pageSize) throws Exception {

        SignInRuleBaseEntity findSignInRuleBase = new SignInRuleBaseEntity();
        findSignInRuleBase.setLhotelGroupCode(lhotelGroupCode);
        QueryResult<SignInRuleBaseEntity> ruleBases = commonService.findAllEQ(SignInRuleBaseEntity.class, findSignInRuleBase, currentPage, pageSize);
        if (CollectionUtils.isEmpty(ruleBases.getResultlist())) {
            QueryResult<SignInBaseDto> signInNull = new QueryResult<>();
            signInNull.setResultlist(Collections.EMPTY_LIST);
            signInNull.setCurrentPage(0);
            signInNull.setTotalrecord(0);
            return signInNull;
        } else {
            List<SignInBaseDto> signInRuleBases = ruleBases.getResultlist().stream()
                    .map(entity -> {
                        try {

                            return selectSignRuleDetail(entity);
                        } catch (Exception e) {
                            throw new SysException(BaseSysExceptionEnum.BASE_FUCATION_OPTION, e);
                        }
                    }).collect(Collectors.toList());
            QueryResult<SignInBaseDto> res = new QueryResult<>();
            res.setTotalrecord(ruleBases.getTotalrecord());
            res.setCurrentPage(ruleBases.getCurrentPage());
            res.setResultlist(signInRuleBases);
            return res;
        }
    }

    @Override
    public SignInBaseDto getSignInBase(String lhotelGroupCode, String code) throws Exception {
        SignInRuleBaseEntity findSignInRuleBase = new SignInRuleBaseEntity();
        findSignInRuleBase.setLhotelGroupCode(lhotelGroupCode);
        findSignInRuleBase.setCode(code);
        SignInRuleBaseEntity qres = commonService.findOnlyOneEQ(SignInRuleBaseEntity.class, findSignInRuleBase);
        if (null == qres) {
            return null;
        } else {
            return selectSignRuleDetail(qres);
        }
    }

    @Override
    public QueryResult<SignInDetailEntity> signInDetail(Date dateMonth, String lhotelGroupCode, String memberNo) throws Exception {
        Date monthFirstDay = CalendarUtils.getStartTimeOfMonth(dateMonth);
        Date monthLastDay = CalendarUtils.getEndTimeOfMonth(dateMonth);
        L2RCondition condition = new L2RCondition();
        condition.setAndConditions(
                new ConditionDetail[]{
                        new ConditionDetail(SignInDetailEntity.SignInDetailEntity_.signInDate.toString(), CriteriaUtil.Operator.LTE, monthLastDay),
                        new ConditionDetail(SignInDetailEntity.SignInDetailEntity_.signInDate.toString(), CriteriaUtil.Operator.GTE, monthFirstDay),
                        new ConditionDetail(SignInDetailEntity.SignInDetailEntity_.memberNo.toString(), CriteriaUtil.Operator.EQ, memberNo),
                        new ConditionDetail(SignInDetailEntity.BaseEntity_.lhotelGroupCode.toString(), CriteriaUtil.Operator.EQ, lhotelGroupCode),
                }
        );
        QueryResult<SignInDetailEntity> details = commonService.findAllByCondition(SignInDetailEntity.class, condition);
        return details;
    }

    @Override
    @Transactional
    public void saveReissue(SignInReissueBaseEntity reissueBase, List<SignInReissueDetailShareEntity> shareDetails) throws Exception {
        commonDao.saveOrMerge(reissueBase);
        commonDao.mergeList(shareDetails);
    }

    @Override
    public boolean isEveryAward(int dayNum, String couldLoopDraw) {
        return dayNum == 1 && DefaultValue.T.equals(couldLoopDraw);
    }

    @Override
    public boolean isRuleBaseExit(String lhotelGroupCode, String code, String title) throws Exception {
        SignInRuleBaseEntity find = new SignInRuleBaseEntity();
        find.setLhotelGroupCode(lhotelGroupCode);
        find.setCode(code);
        find.setTitle(title);
        return 0 < commonService.getCountAllEQ(SignInRuleBaseEntity.class, find, null);
    }

    @Override
    public long countRuleBaseExit(String lhotelGroupCode, String code, String title) throws Exception {
        SignInRuleBaseEntity find = new SignInRuleBaseEntity();
        find.setLhotelGroupCode(lhotelGroupCode);
        find.setCode(code);
        find.setTitle(title);
        return  commonService.getCountAllEQ(SignInRuleBaseEntity.class, find, null);
    }

    @Override
    public boolean isAwardBaseExit(String lhotelGroupCode, String code) {
        SignInAwardBaseEntity find = new SignInAwardBaseEntity();
        find.setLhotelGroupCode(lhotelGroupCode);
        find.setCode(code);
        try {
            return 0 < commonService.getCountAllEQ(SignInAwardBaseEntity.class, find, null);
        } catch (Exception e) {
            throw new SysException(BaseSysExceptionEnum.BASE_FUCATION_OPTION, e);
        }
    }

    @Override
    public String generateSignInRuleBaseCode(String codeType) {
        Lock lock = signInCodeLock.obtain(codeType);
        try {
            if (lock.tryLock(5, TimeUnit.SECONDS)) {
                try {
                    List params = new ArrayList<>();
                    params.add(codeType);
                    String no = commonService.findOneFieldByProcedure("create_No", params);
                    return no;
                } finally {
                    lock.unlock();
                }
            } else {
                throw new SysException(BaseSysExceptionEnum.BASE_FUCATION_OPTION, "generateSignInRuleBaseCode block.[codeType] is " + codeType);
            }
        } catch (Exception e) {
            throw new SysException(BaseSysExceptionEnum.BASE_FUCATION_OPTION, e);
        }
    }

    @Override
    public SignInAwardTypeEntity findAwardType(String lhotelGroupCode, String type) throws Exception {
        SignInAwardTypeEntity find = new SignInAwardTypeEntity();
        find.setLhotelGroupCode(lhotelGroupCode);
        find.setType(type);
        return commonService.findOnlyOneEQ(SignInAwardTypeEntity.class, find);
    }

    @Override
    @Transactional
    public void saveSignInRuleBase(SignInRuleBaseEntity newSignInRule, SignInRuleBaseEntity nowSignInRule, List<SignInAwardBaseEntity> awardEntities, List<SignInAwardMappingEntity> awardMappings, List<SignInReissueRuleEntity> signInReissueRuleEntities, List<SignInReissueMappingEntity> signInReissueMappingEntities) throws Exception {
        commonDao.save(newSignInRule);
        commonDao.saveList(awardEntities);
        commonDao.saveList(awardMappings);
        if (null != nowSignInRule) {
            commonDao.merge(nowSignInRule);
        }
        if (CollectionUtils.isNotEmpty(signInReissueRuleEntities)) {
            commonDao.saveList(signInReissueRuleEntities);
            commonDao.saveList(signInReissueMappingEntities);
        }
    }

    @Override
    public boolean signInRuleIsInUse(String lhotelGroupCode, String signInRuleCode) throws Exception {
        SignInRuleBaseEntity find = new SignInRuleBaseEntity();
        find.setCode(signInRuleCode);
        find.setLhotelGroupCode(lhotelGroupCode);
        SignInRuleBaseEntity signInRuleBase = commonService.findOnlyOneEQ(SignInRuleBaseEntity.class, find);
        L2RAssert.isTrue(null == signInRuleBase, new SysException(BaseSysExceptionEnum.BASE_FUCATION_OPTION, "活动不存在.[code] " + signInRuleCode));
        return _isInUse(signInRuleBase);
    }

    @Override
    public SignInRuleBaseEntity findPreviousRuleBaseEntity(SignInRuleBaseEntity signInRuleBase) throws Exception {
        if(null == signInRuleBase){return null;}
        Date previousEndDate = DateUtil.addMonths(signInRuleBase.getStartMonth(), -1);
        String lholetGroupCode = signInRuleBase.getLhotelGroupCode();
        SignInRuleBaseEntity findPre = new SignInRuleBaseEntity();
        findPre.setEndMonth(previousEndDate);
        findPre.setLhotelGroupCode(lholetGroupCode);
        return commonService.findOnlyOneEQ(SignInRuleBaseEntity.class, findPre);
    }

    boolean _isInUse(SignInRuleBaseEntity signInRuleBase) {
        Date now = new Date();
        Date startMonth = signInRuleBase.getStartMonth();
        L2RAssert.isTrue(null == startMonth, new SysException(BaseSysExceptionEnum.INVALID_PARA, "[endMonth] 数据不全"));

        boolean isAutoExtension = DefaultValue.T.equals(signInRuleBase.getIsAutoExtension());
        if (isAutoExtension) {
            return now.after(startMonth);
        } else {
            Date endMonth = signInRuleBase.getEndMonth();
            L2RAssert.isTrue(null == endMonth, new SysException(BaseSysExceptionEnum.INVALID_PARA, "[endMonth] 数据不全"));
            return now.after(startMonth) && now.before(DateUtil.addMonths(endMonth,1));
        }
    }

    boolean _isOver(SignInRuleBaseEntity signInRuleBase) {
        Date now = new Date();
        boolean isAutoExtension = DefaultValue.T.equals(signInRuleBase.getIsAutoExtension());
        if (isAutoExtension) {
            return false;
        } else {
            Date endMonth = signInRuleBase.getEndMonth();
            L2RAssert.isTrue(null == endMonth, new SysException(BaseSysExceptionEnum.INVALID_PARA, "[endMonth] 数据不全"));
            return now.after(DateUtil.addMonths(endMonth,1));
        }
    }

    @Override
    @Transactional
    public void modifySignInRule(ModifySignInRule modifySignInRule) throws Exception {
        List<SignInRuleBaseEntity> signInRuleBasesToModify = modifySignInRule.getSignInRuleBasesToModify();
        List<SignInAwardBaseEntity> newSignInAwardBases = modifySignInRule.getNewSignInAwardBases();
        List<SignInAwardMappingEntity> newSignInAwardMappingEntities = modifySignInRule.getNewSignInAwardMappingEntities();
        List<SignInAwardBaseEntity> delSignInAwardBases = modifySignInRule.getDelSignInAwardBases();
        List<SignInAwardMappingEntity> delSignInAwardMappingEntities = modifySignInRule.getDelSignInAwardMappingEntities();
        List<SignInReissueRuleEntity> newSignInReissueBaseEntities = modifySignInRule.getNewSignInReissueRuleEntities();
        List<SignInReissueMappingEntity> newSignInReissueMappingEntities = modifySignInRule.getNewSignInReissueMappingEntities();
        List<SignInReissueRuleEntity> delSignInReissueBaseEntities = modifySignInRule.getDelSignInReissueRuleEntities();
        List<SignInReissueMappingEntity> delSignInReissueMappingEntities = modifySignInRule.getDelSignInReissueMappingEntities();
        if (CollectionUtils.isNotEmpty(signInRuleBasesToModify)) {
            commonDao.mergeList(signInRuleBasesToModify);
        }
        if (CollectionUtils.isNotEmpty(delSignInAwardBases)) {
            List<Long> ids = delSignInAwardBases.stream().map(BaseEntity::getId).collect(Collectors.toList());
            commonDao.delete(SignInAwardBaseEntity.class, ids.toArray());
        }
        if (CollectionUtils.isNotEmpty(delSignInAwardMappingEntities)) {
            List<Long> ids = delSignInAwardMappingEntities.stream().map(BaseEntity::getId).collect(Collectors.toList());
            commonDao.delete(SignInAwardMappingEntity.class, ids.toArray());
        }

        if (CollectionUtils.isNotEmpty(newSignInAwardBases)) {
            commonDao.saveList(newSignInAwardBases);
        }
        if (CollectionUtils.isNotEmpty(newSignInAwardMappingEntities)) {
            commonDao.saveList(newSignInAwardMappingEntities);
        }

        if (CollectionUtils.isNotEmpty(delSignInReissueBaseEntities)) {
            List<Long> ids = delSignInReissueBaseEntities.stream().map(BaseEntity::getId).collect(Collectors.toList());
            commonDao.delete(SignInReissueRuleEntity.class, ids.toArray());
        }
        if (CollectionUtils.isNotEmpty(delSignInReissueMappingEntities)) {
            List<Long> ids = delSignInReissueMappingEntities.stream().map(BaseEntity::getId).collect(Collectors.toList());
            commonDao.delete(SignInReissueMappingEntity.class, ids.toArray());
        }
        if (CollectionUtils.isNotEmpty(newSignInReissueBaseEntities)) {
            commonDao.saveList(newSignInReissueBaseEntities);
        }
        if (CollectionUtils.isNotEmpty(newSignInReissueMappingEntities)) {
            commonDao.saveList(newSignInReissueMappingEntities);
        }
    }


    QueryResult<SignInAwardMapper> findSignInAwardMapper(String lhotelGroupCode, String ruleCode, Date date) throws Exception {
        List parameters = Arrays.asList(ruleCode, lhotelGroupCode);
        return commonService.findByNative(signInAwardMapperQuery(), null, parameters, null, SignInAwardMapper.class, null, null);
    }

    private String signInAwardMapperQuery() {
        String sql = "SELECT \n" +
                "  siam.rule_base_code AS ruleCode,\n" +
                "  siam.award_code AS awardCode ,\n" +
                "  siab.`is_continuous` AS isContinuous,\n" +
                "  siab.`value` AS value ,\n" +
                "  siab.`type` AS `type`,\n" +
                "  siat.`name` AS typeName,\n" +
                "  siab.`day_step` AS dayStep,\n" +
                "  siab.`description` AS description,\n" +
                "  siab.`is_halt` AS isHalt\n" +
                "FROM\n" +
                "  sign_in_award_mapping AS siam \n" +
                "  LEFT JOIN sign_in_award_base AS siab  ON siam.`award_code` = siab.`code` \n" +
                "  LEFT JOIN sign_in_award_type AS siat ON siat.`type` = siab.`type`\n" +
                "WHERE siam.`rule_base_code` = ? \n" +
                "  AND siam.`lhotel_group_code` = ? " +

                "order by dayStep";
        return sql;
    }

    QueryResult<SignInReissueMapper> findSignInReissueMapper(String lhotelGroupCode, String ruleCode, Date date) throws Exception {
        List parameters = Arrays.asList(ruleCode, lhotelGroupCode);
        return commonService.findByNative(signInReissueMapperQuery(), null, parameters, null, SignInReissueMapper.class, null, null);
    }

    private String signInReissueMapperQuery() {
        String sql = "SELECT \n" +
                "  sirm.rule_base_code AS ruleCode,\n" +
                "  sirm.`reissue_code` AS reissueCode ,\n" +
                "  sirr.`name` AS `name`,\n" +
                "  sirr.`rule` AS rule,\n" +
                "  sirr.`type` AS `type`\n" +
                "FROM\n" +
                "  `sign_in_reissue_mapping` AS sirm \n" +
                "  LEFT JOIN `sign_in_reissue_rule` AS sirr  ON sirm.`reissue_code` = sirr.`code` \n" +
                "\n" +
                "WHERE sirm.`rule_base_code` =  ? \n" +
                "  AND sirm.`lhotel_group_code` = ? \n" +

                "  ";
        return sql;
    }

//    private boolean signInRuleBaseIsInUse(SignInBaseDto baseDto){
//        String isAutoExtension = baseDto.getIsAutoExtension();
//        String isInUse = baseDto.getIsInUse();
//        Date startMonth = baseDto.getStartMonth();
//
//    }

}
